home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / ddx / mfb / mfbgc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-28  |  28.4 KB  |  1,293 lines

  1. /***********************************************************
  2. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ******************************************************************/
  24. /* $XConsortium: mfbgc.c,v 5.19 90/03/20 14:48:59 rws Exp $ */
  25. #include "X.h"
  26. #include "Xmd.h"
  27. #include "Xproto.h"
  28. #include "dixfontstr.h"
  29. #include "fontstruct.h"
  30. #include "gcstruct.h"
  31. #include "windowstr.h"
  32. #include "pixmapstr.h"
  33. #include "scrnintstr.h"
  34. #include "region.h"
  35.  
  36. #include "mfb.h"
  37. #include "mistruct.h"
  38.  
  39. #include "maskbits.h"
  40.  
  41. static void mfbDestroyOps();
  42.  
  43. static GCFuncs    mfbFuncs = {
  44.     mfbValidateGC,
  45.     mfbChangeGC,
  46.     mfbCopyGC,
  47.     mfbDestroyGC,
  48.     mfbChangeClip,
  49.     mfbDestroyClip,
  50.     mfbCopyClip,
  51. };
  52.  
  53. static GCOps    whiteTECopyOps = {
  54.     mfbWhiteSolidFS,
  55.     mfbSetSpans,
  56.     mfbPutImage,
  57.     mfbCopyArea,
  58.     mfbCopyPlane,
  59.     mfbPolyPoint,
  60.     mfbLineSS,
  61.     mfbSegmentSS,
  62.     miPolyRectangle,
  63.     mfbZeroPolyArcSS,
  64.     miFillPolygon,
  65.     mfbPolyFillRect,
  66.     mfbPolyFillArcSolid,
  67.     miPolyText8,
  68.     miPolyText16,
  69.     miImageText8,
  70.     miImageText16,
  71.     mfbTEGlyphBltWhite,
  72.     mfbPolyGlyphBltWhite,
  73.     mfbSolidPP,
  74.     NULL,
  75. };
  76.  
  77. static GCOps    blackTECopyOps = {
  78.     mfbBlackSolidFS,
  79.     mfbSetSpans,
  80.     mfbPutImage,
  81.     mfbCopyArea,
  82.     mfbCopyPlane,
  83.     mfbPolyPoint,
  84.     mfbLineSS,
  85.     mfbSegmentSS,
  86.     miPolyRectangle,
  87.     mfbZeroPolyArcSS,
  88.     miFillPolygon,
  89.     mfbPolyFillRect,
  90.     mfbPolyFillArcSolid,
  91.     miPolyText8,
  92.     miPolyText16,
  93.     miImageText8,
  94.     miImageText16,
  95.     mfbTEGlyphBltBlack,
  96.     mfbPolyGlyphBltBlack,
  97.     mfbSolidPP,
  98.     NULL,
  99. };
  100.  
  101. static GCOps    whiteTEInvertOps = {
  102.     mfbInvertSolidFS,
  103.     mfbSetSpans,
  104.     mfbPutImage,
  105.     mfbCopyArea,
  106.     mfbCopyPlane,
  107.     mfbPolyPoint,
  108.     mfbLineSS,
  109.     mfbSegmentSS,
  110.     miPolyRectangle,
  111.     miZeroPolyArc,
  112.     miFillPolygon,
  113.     mfbPolyFillRect,
  114.     mfbPolyFillArcSolid,
  115.     miPolyText8,
  116.     miPolyText16,
  117.     miImageText8,
  118.     miImageText16,
  119.     mfbTEGlyphBltWhite,
  120.     mfbPolyGlyphBltInvert,
  121.     mfbSolidPP,
  122.     NULL,
  123. };
  124.  
  125. static GCOps    blackTEInvertOps = {
  126.     mfbInvertSolidFS,
  127.     mfbSetSpans,
  128.     mfbPutImage,
  129.     mfbCopyArea,
  130.     mfbCopyPlane,
  131.     mfbPolyPoint,
  132.     mfbLineSS,
  133.     mfbSegmentSS,
  134.     miPolyRectangle,
  135.     miZeroPolyArc,
  136.     miFillPolygon,
  137.     mfbPolyFillRect,
  138.     mfbPolyFillArcSolid,
  139.     miPolyText8,
  140.     miPolyText16,
  141.     miImageText8,
  142.     miImageText16,
  143.     mfbTEGlyphBltBlack,
  144.     mfbPolyGlyphBltInvert,
  145.     mfbSolidPP,
  146.     NULL,
  147. };
  148.  
  149. static GCOps    whiteCopyOps = {
  150.     mfbWhiteSolidFS,
  151.     mfbSetSpans,
  152.     mfbPutImage,
  153.     mfbCopyArea,
  154.     mfbCopyPlane,
  155.     mfbPolyPoint,
  156.     mfbLineSS,
  157.     mfbSegmentSS,
  158.     miPolyRectangle,
  159.     mfbZeroPolyArcSS,
  160.     miFillPolygon,
  161.     mfbPolyFillRect,
  162.     mfbPolyFillArcSolid,
  163.     miPolyText8,
  164.     miPolyText16,
  165.     miImageText8,
  166.     miImageText16,
  167.     mfbImageGlyphBltWhite,
  168.     mfbPolyGlyphBltWhite,
  169.     mfbSolidPP,
  170.     NULL,
  171. };
  172.  
  173. static GCOps    blackCopyOps = {
  174.     mfbBlackSolidFS,
  175.     mfbSetSpans,
  176.     mfbPutImage,
  177.     mfbCopyArea,
  178.     mfbCopyPlane,
  179.     mfbPolyPoint,
  180.     mfbLineSS,
  181.     mfbSegmentSS,
  182.     miPolyRectangle,
  183.     mfbZeroPolyArcSS,
  184.     miFillPolygon,
  185.     mfbPolyFillRect,
  186.     mfbPolyFillArcSolid,
  187.     miPolyText8,
  188.     miPolyText16,
  189.     miImageText8,
  190.     miImageText16,
  191.     mfbImageGlyphBltBlack,
  192.     mfbPolyGlyphBltBlack,
  193.     mfbSolidPP,
  194.     NULL,
  195. };
  196.  
  197. static GCOps    whiteInvertOps = {
  198.     mfbInvertSolidFS,
  199.     mfbSetSpans,
  200.     mfbPutImage,
  201.     mfbCopyArea,
  202.     mfbCopyPlane,
  203.     mfbPolyPoint,
  204.     mfbLineSS,
  205.     mfbSegmentSS,
  206.     miPolyRectangle,
  207.     miZeroPolyArc,
  208.     miFillPolygon,
  209.     mfbPolyFillRect,
  210.     mfbPolyFillArcSolid,
  211.     miPolyText8,
  212.     miPolyText16,
  213.     miImageText8,
  214.     miImageText16,
  215.     mfbImageGlyphBltWhite,
  216.     mfbPolyGlyphBltInvert,
  217.     mfbSolidPP,
  218.     NULL,
  219. };
  220.  
  221. static GCOps    blackInvertOps = {
  222.     mfbInvertSolidFS,
  223.     mfbSetSpans,
  224.     mfbPutImage,
  225.     mfbCopyArea,
  226.     mfbCopyPlane,
  227.     mfbPolyPoint,
  228.     mfbLineSS,
  229.     mfbSegmentSS,
  230.     miPolyRectangle,
  231.     miZeroPolyArc,
  232.     miFillPolygon,
  233.     mfbPolyFillRect,
  234.     mfbPolyFillArcSolid,
  235.     miPolyText8,
  236.     miPolyText16,
  237.     miImageText8,
  238.     miImageText16,
  239.     mfbImageGlyphBltBlack,
  240.     mfbPolyGlyphBltInvert,
  241.     mfbSolidPP,
  242.     NULL,
  243. };
  244.  
  245. static GCOps    whiteWhiteCopyOps = {
  246.     mfbWhiteSolidFS,
  247.     mfbSetSpans,
  248.     mfbPutImage,
  249.     mfbCopyArea,
  250.     mfbCopyPlane,
  251.     mfbPolyPoint,
  252.     mfbLineSS,
  253.     mfbSegmentSS,
  254.     miPolyRectangle,
  255.     mfbZeroPolyArcSS,
  256.     miFillPolygon,
  257.     mfbPolyFillRect,
  258.     mfbPolyFillArcSolid,
  259.     miPolyText8,
  260.     miPolyText16,
  261.     miImageText8,
  262.     miImageText16,
  263.     miImageGlyphBlt,
  264.     mfbPolyGlyphBltWhite,
  265.     mfbSolidPP,
  266.     NULL,
  267. };
  268.  
  269. static GCOps    blackBlackCopyOps = {
  270.     mfbBlackSolidFS,
  271.     mfbSetSpans,
  272.     mfbPutImage,
  273.     mfbCopyArea,
  274.     mfbCopyPlane,
  275.     mfbPolyPoint,
  276.     mfbLineSS,
  277.     mfbSegmentSS,
  278.     miPolyRectangle,
  279.     mfbZeroPolyArcSS,
  280.     miFillPolygon,
  281.     mfbPolyFillRect,
  282.     mfbPolyFillArcSolid,
  283.     miPolyText8,
  284.     miPolyText16,
  285.     miImageText8,
  286.     miImageText16,
  287.     miImageGlyphBlt,
  288.     mfbPolyGlyphBltBlack,
  289.     mfbSolidPP,
  290.     NULL,
  291. };
  292.  
  293. static GCOps    fgEqBgInvertOps = {
  294.     mfbInvertSolidFS,
  295.     mfbSetSpans,
  296.     mfbPutImage,
  297.     mfbCopyArea,
  298.     mfbCopyPlane,
  299.     mfbPolyPoint,
  300.     mfbLineSS,
  301.     mfbSegmentSS,
  302.     miPolyRectangle,
  303.     miZeroPolyArc,
  304.     miFillPolygon,
  305.     mfbPolyFillRect,
  306.     mfbPolyFillArcSolid,
  307.     miPolyText8,
  308.     miPolyText16,
  309.     miImageText8,
  310.     miImageText16,
  311.     miImageGlyphBlt,
  312.     mfbPolyGlyphBltInvert,
  313.     mfbSolidPP,
  314.     NULL,
  315. };
  316.  
  317. struct commonOps {
  318.     int            fg, bg;
  319.     int            rrop;
  320.     int            terminalFont;
  321.     GCOps        *ops;
  322.     void        (*fillArea)();
  323. };
  324.  
  325. static struct commonOps mfbCommonOps[] = {
  326.     { 1, 0, RROP_WHITE, 1, &whiteTECopyOps, mfbSolidWhiteArea },
  327.     { 0, 1, RROP_BLACK, 1, &blackTECopyOps, mfbSolidBlackArea },
  328.     { 1, 0, RROP_INVERT, 1, &whiteTEInvertOps, mfbSolidInvertArea },
  329.     { 0, 1, RROP_INVERT, 1, &blackTEInvertOps, mfbSolidInvertArea },
  330.     { 1, 0, RROP_WHITE, 0, &whiteCopyOps, mfbSolidWhiteArea },
  331.     { 0, 1, RROP_BLACK, 0, &blackCopyOps, mfbSolidBlackArea },
  332.     { 1, 0, RROP_INVERT, 0, &whiteInvertOps, mfbSolidInvertArea },
  333.     { 0, 1, RROP_INVERT, 0, &blackInvertOps, mfbSolidInvertArea },
  334.     { 1, 1, RROP_WHITE, 0, &whiteWhiteCopyOps, mfbSolidWhiteArea },
  335.     { 0, 0, RROP_BLACK, 0, &blackBlackCopyOps, mfbSolidBlackArea },
  336.     { 1, 1, RROP_INVERT, 0, &fgEqBgInvertOps, mfbSolidInvertArea },
  337.     { 0, 0, RROP_INVERT, 0, &fgEqBgInvertOps, mfbSolidInvertArea },
  338. };
  339.  
  340. #define numberCommonOps    (sizeof (mfbCommonOps) / sizeof (mfbCommonOps[0]))
  341.  
  342. static GCOps *
  343. matchCommon (pGC)
  344.     GCPtr   pGC;
  345. {
  346.     int    i;
  347.     struct commonOps    *cop;
  348.     mfbPrivGC        *priv;
  349.  
  350.     if (pGC->lineWidth != 0)
  351.     return 0;
  352.     if (pGC->lineStyle != LineSolid)
  353.     return 0;
  354.     if (pGC->fillStyle != FillSolid)
  355.     return 0;
  356.     if (!pGC->font ||
  357.         pGC->font->pFI->maxbounds.metrics.rightSideBearing -
  358.     pGC->font->pFI->minbounds.metrics.leftSideBearing > 32)
  359.     return 0;
  360.     priv = (mfbPrivGC *) pGC->devPrivates[mfbGCPrivateIndex].ptr;
  361.     for (i = 0; i < numberCommonOps; i++) {
  362.     cop = &mfbCommonOps[i];
  363.     if (pGC->fgPixel != cop->fg)
  364.         continue;
  365.     if (pGC->bgPixel != cop->bg)
  366.         continue;
  367.     if (priv->rop != cop->rrop)
  368.         continue;
  369.     if (cop->terminalFont && !pGC->font->pFI->terminalFont)
  370.         continue;
  371.     priv->FillArea = cop->fillArea;
  372.     return cop->ops;
  373.     }
  374.     return 0;
  375. }
  376.  
  377. Bool
  378. mfbCreateGC(pGC)
  379.     register GCPtr pGC;
  380. {
  381.     mfbPrivGC     *pPriv;
  382.  
  383.     pGC->clientClip = NULL;
  384.     pGC->clientClipType = CT_NONE;
  385.     
  386.     /* some of the output primitives aren't really necessary, since
  387.        they will be filled in ValidateGC because of dix/CreateGC()
  388.        setting all the change bits.  Others are necessary because although
  389.        they depend on being a monochrome frame buffer, they don't change 
  390.     */
  391.  
  392.     pGC->ops = &whiteCopyOps;
  393.     pGC->funcs = &mfbFuncs;
  394.  
  395.     /* mfb wants to translate before scan convesion */
  396.     pGC->miTranslate = 1;
  397.  
  398.     pPriv = (mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr);
  399.     pPriv->rop = mfbReduceRop(pGC->alu, pGC->fgPixel);
  400.     pPriv->fExpose = TRUE;
  401.     pPriv->pRotatedPixmap = NullPixmap;
  402.     pPriv->freeCompClip = FALSE;
  403.     pPriv->FillArea = mfbSolidInvertArea;
  404.     return TRUE;
  405. }
  406.  
  407. /*ARGSUSED*/
  408. void
  409. mfbChangeGC(pGC, mask)
  410.     GC        *pGC;
  411.     BITS32  mask;
  412. {
  413.     return;
  414. }
  415.  
  416. /*ARGSUSED*/
  417. void
  418. mfbCopyGC (pGCSrc, changes, pGCDst)
  419.     GCPtr    pGCSrc;
  420.     Mask     changes;
  421.     GCPtr    pGCDst;
  422. {
  423.     return;
  424. }
  425.  
  426. void
  427. mfbDestroyGC(pGC)
  428.     GC             *pGC;
  429. {
  430.     mfbPrivGC *pPriv;
  431.  
  432.     pPriv = (mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr);
  433.     if (pPriv->pRotatedPixmap)
  434.     mfbDestroyPixmap(pPriv->pRotatedPixmap);
  435.     if (pPriv->freeCompClip)
  436.     (*pGC->pScreen->RegionDestroy)(pPriv->pCompositeClip);
  437.     mfbDestroyOps (pGC->ops);
  438. }
  439.  
  440. /*
  441.  * create a private op array for a gc
  442.  */
  443.  
  444. static GCOps *
  445. mfbCreateOps (prototype)
  446.     GCOps    *prototype;
  447. {
  448.     GCOps    *ret;
  449.     extern Bool    Must_have_memory;
  450.  
  451.     /* XXX */ Must_have_memory = TRUE;
  452.     ret = (GCOps *) xalloc (sizeof *ret);
  453.     /* XXX */ Must_have_memory = FALSE;
  454.     if (!ret)
  455.     return 0;
  456.     *ret = *prototype;
  457.     ret->devPrivate.val = 1;
  458.     return ret;
  459. }
  460.  
  461. static void
  462. mfbDestroyOps (ops)
  463.     GCOps   *ops;
  464. {
  465.     if (ops->devPrivate.val)
  466.     xfree (ops);
  467. }
  468.  
  469. /* Clipping conventions
  470.     if the drawable is a window
  471.         CT_REGION ==> pCompositeClip really is the composite
  472.         CT_other ==> pCompositeClip is the window clip region
  473.     if the drawable is a pixmap
  474.         CT_REGION ==> pCompositeClip is the translated client region
  475.         clipped to the pixmap boundary
  476.         CT_other ==> pCompositeClip is the pixmap bounding box
  477. */
  478.  
  479. /*ARGSUSED*/
  480. void
  481. mfbValidateGC(pGC, changes, pDrawable)
  482.     register GCPtr     pGC;
  483.     Mask         changes;
  484.     DrawablePtr     pDrawable;
  485. {
  486.     register mfbPrivGCPtr    devPriv;
  487.     WindowPtr pWin;
  488.     int mask;            /* stateChanges */
  489.     int index;            /* used for stepping through bitfields */
  490.     int    xrot, yrot;        /* rotations for tile and stipple pattern */
  491.     int rrop;            /* reduced rasterop */
  492.                 /* flags for changing the proc vector 
  493.                    and updating things in devPriv
  494.                 */
  495.     int new_rotate, new_rrop,  new_line, new_text, new_fill;
  496.     DDXPointRec    oldOrg;        /* origin of thing GC was last used with */
  497.  
  498.     oldOrg = pGC->lastWinOrg;
  499.  
  500.     pGC->lastWinOrg.x = pDrawable->x;
  501.     pGC->lastWinOrg.y = pDrawable->y;
  502.     if (pDrawable->type == DRAWABLE_WINDOW)
  503.     pWin = (WindowPtr)pDrawable;
  504.     else
  505.     pWin = (WindowPtr)NULL;
  506.  
  507.     /* we need to re-rotate the tile if the previous window/pixmap
  508.        origin (oldOrg) differs from the new window/pixmap origin
  509.        (pGC->lastWinOrg)
  510.     */
  511.     new_rotate = (oldOrg.x != pGC->lastWinOrg.x) ||
  512.          (oldOrg.y != pGC->lastWinOrg.y);
  513.  
  514.     devPriv = ((mfbPrivGCPtr) (pGC->devPrivates[mfbGCPrivateIndex].ptr));
  515.  
  516.     /*
  517.     if the client clip is different or moved OR
  518.     the subwindowMode has changed OR
  519.     the window's clip has changed since the last validation
  520.     we need to recompute the composite clip
  521.     */
  522.     if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
  523.     (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
  524.        )
  525.     {
  526.     ScreenPtr pScreen = pGC->pScreen;
  527.  
  528.     if (pWin)
  529.     {
  530.         Bool freeTmpClip, freeCompClip;
  531.         RegionPtr pregWin;        /* clip for this window, without
  532.                        client clip */
  533.  
  534.         if (pGC->subWindowMode == IncludeInferiors)
  535.         {
  536.             pregWin = NotClippedByChildren(pWin);
  537.         freeTmpClip = TRUE;
  538.         }
  539.         else
  540.         {
  541.             pregWin = &pWin->clipList;
  542.         freeTmpClip = FALSE;
  543.         }
  544.         freeCompClip = devPriv->freeCompClip;
  545.  
  546.         /* if there is no client clip, we can get by with
  547.            just keeping the pointer we got, and remembering
  548.            whether or not should destroy (or maybe re-use)
  549.            it later.  this way, we avoid unnecessary copying
  550.            of regions.  (this wins especially if many clients clip
  551.            by children and have no client clip.)
  552.         */
  553.         if (pGC->clientClipType == CT_NONE)
  554.         {
  555.             if(freeCompClip) 
  556.             (*pScreen->RegionDestroy) (devPriv->pCompositeClip);
  557.             devPriv->pCompositeClip = pregWin;
  558.             devPriv->freeCompClip = freeTmpClip;
  559.         }
  560.         else
  561.         {
  562.         /* we need one 'real' region to put into the composite
  563.            clip.
  564.             if pregWin and the current composite clip 
  565.            are real, we can get rid of one.
  566.             if the current composite clip is real and
  567.            pregWin isn't, intersect the client clip and
  568.            pregWin into the existing composite clip.
  569.             if pregWin is real and the current composite
  570.            clip isn't, intersect pregWin with the client clip
  571.            and replace the composite clip with it.
  572.             if neither is real, create a new region and
  573.            do the intersection into it.
  574.         */
  575.  
  576.         (*pScreen->TranslateRegion)(pGC->clientClip,
  577.                         pDrawable->x + pGC->clipOrg.x,
  578.                         pDrawable->y + pGC->clipOrg.y);
  579.                           
  580.         if (freeCompClip)
  581.         {
  582.             (*pScreen->Intersect)(devPriv->pCompositeClip,
  583.                       pregWin, pGC->clientClip);
  584.             if (freeTmpClip)
  585.             (*pScreen->RegionDestroy)(pregWin);
  586.         }
  587.         else if (freeTmpClip)
  588.         {
  589.             (*pScreen->Intersect)(pregWin, pregWin, pGC->clientClip);
  590.             devPriv->pCompositeClip = pregWin;
  591.         }
  592.         else
  593.         {
  594.             devPriv->pCompositeClip = (*pScreen->RegionCreate)(NullBox,
  595.                                        0);
  596.             (*pScreen->Intersect)(devPriv->pCompositeClip,
  597.                       pregWin, pGC->clientClip);
  598.         }
  599.         devPriv->freeCompClip = TRUE;
  600.         (*pScreen->TranslateRegion)(pGC->clientClip,
  601.                         -(pDrawable->x + pGC->clipOrg.x),
  602.                         -(pDrawable->y + pGC->clipOrg.y));
  603.                           
  604.         }
  605.     } /* end of composite clip for a window */
  606.     else
  607.     {
  608.         BoxRec pixbounds;
  609.  
  610.         /* XXX should we translate by drawable.x/y here ? */
  611.         pixbounds.x1 = 0;
  612.         pixbounds.y1 = 0;
  613.         pixbounds.x2 = pDrawable->width;
  614.         pixbounds.y2 = pDrawable->height;
  615.  
  616.         if (devPriv->freeCompClip)
  617.             (*pScreen->RegionReset)(devPriv->pCompositeClip, &pixbounds);
  618.         else
  619.         {
  620.         devPriv->freeCompClip = TRUE;
  621.         devPriv->pCompositeClip = (*pScreen->RegionCreate)(&pixbounds,
  622.                                    1);
  623.         }
  624.  
  625.         if (pGC->clientClipType == CT_REGION)
  626.         {
  627.         (*pScreen->TranslateRegion)(devPriv->pCompositeClip,
  628.                         -pGC->clipOrg.x, -pGC->clipOrg.y);
  629.         (*pScreen->Intersect)(devPriv->pCompositeClip,
  630.                       devPriv->pCompositeClip,
  631.                       pGC->clientClip);
  632.         (*pScreen->TranslateRegion)(devPriv->pCompositeClip,
  633.                         pGC->clipOrg.x, pGC->clipOrg.y);
  634.         }
  635.     } /* end of composite clip for pixmap */
  636.     }
  637.  
  638.     new_rrop = FALSE;
  639.     new_line = FALSE;
  640.     new_text = FALSE;
  641.     new_fill = FALSE;
  642.  
  643.     mask = changes;
  644.     while (mask)
  645.     {
  646.     index = lowbit (mask);
  647.     mask &= ~index;
  648.  
  649.     /* this switch acculmulates a list of which procedures
  650.        might have to change due to changes in the GC.  in
  651.        some cases (e.g. changing one 16 bit tile for another)
  652.        we might not really need a change, but the code is
  653.        being paranoid.
  654.        this sort of batching wins if, for example, the alu
  655.        and the font have been changed, or any other pair
  656.        of items that both change the same thing.
  657.     */
  658.     switch (index)
  659.     {
  660.       case GCFunction:
  661.       case GCForeground:
  662.         new_rrop = TRUE;
  663.         break;
  664.       case GCPlaneMask:
  665.         break;
  666.       case GCBackground:
  667.         new_rrop = TRUE;    /* for opaque stipples */
  668.         break;
  669.       case GCLineStyle:
  670.       case GCLineWidth:
  671.       case GCJoinStyle:
  672.         new_line = TRUE;
  673.         break;
  674.       case GCCapStyle:
  675.         break;
  676.       case GCFillStyle:
  677.         new_fill = TRUE;
  678.         break;
  679.       case GCFillRule:
  680.         break;
  681.       case GCTile:
  682.         if(pGC->tileIsPixel)
  683.         break;
  684.         new_rotate = TRUE;
  685.         new_fill = TRUE;
  686.         break;
  687.  
  688.       case GCStipple:
  689.         if(pGC->stipple == (PixmapPtr)NULL)
  690.         break;
  691.         new_rotate = TRUE;
  692.         new_fill = TRUE;
  693.         break;
  694.  
  695.       case GCTileStipXOrigin:
  696.         new_rotate = TRUE;
  697.         break;
  698.  
  699.       case GCTileStipYOrigin:
  700.         new_rotate = TRUE;
  701.         break;
  702.  
  703.       case GCFont:
  704.         new_text = TRUE;
  705.         break;
  706.       case GCSubwindowMode:
  707.         break;
  708.       case GCGraphicsExposures:
  709.         break;
  710.       case GCClipXOrigin:
  711.         break;
  712.       case GCClipYOrigin:
  713.         break;
  714.       case GCClipMask:
  715.         break;
  716.       case GCDashOffset:
  717.         break;
  718.       case GCDashList:
  719.         break;
  720.       case GCArcMode:
  721.         break;
  722.       default:
  723.         break;
  724.     }
  725.     }
  726.  
  727.     /* deal with the changes we've collected .
  728.        new_rrop must be done first because subsequent things
  729.        depend on it.
  730.     */
  731.  
  732.     if(new_rotate || new_fill)
  733.     {
  734.     Bool new_pix = FALSE;
  735.  
  736.     /* figure out how much to rotate */
  737.     xrot = pGC->patOrg.x;
  738.     yrot = pGC->patOrg.y;
  739.     xrot += pDrawable->x;
  740.     yrot += pDrawable->y;
  741.  
  742.     switch (pGC->fillStyle)
  743.     {
  744.     case FillTiled:
  745.         /* copy current tile and stipple */
  746.         if (!pGC->tileIsPixel && (pGC->tile.pixmap->drawable.width <= 32) &&
  747.             !(pGC->tile.pixmap->drawable.width & (pGC->tile.pixmap->drawable.width - 1)))
  748.         {
  749.         mfbCopyRotatePixmap(pGC->tile.pixmap,
  750.                     &devPriv->pRotatedPixmap, xrot, yrot);
  751.         new_pix = TRUE;
  752.         }
  753.         break;
  754.     case FillStippled:
  755.     case FillOpaqueStippled:
  756.         if (pGC->stipple && (pGC->stipple->drawable.width <= 32) &&
  757.             !(pGC->stipple->drawable.width & (pGC->stipple->drawable.width - 1)))
  758.         {
  759.             if (pGC->stipple == pGC->pScreen->PixmapPerDepth[0])
  760.             {
  761.             if (pGC->stipple->drawable.width != 32)
  762.             mfbPadPixmap(pGC->stipple);
  763.             if (devPriv->pRotatedPixmap)
  764.             mfbDestroyPixmap(devPriv->pRotatedPixmap);
  765.             devPriv->pRotatedPixmap = pGC->stipple;
  766.             ++devPriv->pRotatedPixmap->refcnt;
  767.             }
  768.             else
  769.             {
  770.             mfbCopyRotatePixmap(pGC->stipple,
  771.                     &devPriv->pRotatedPixmap, xrot, yrot);
  772.             }
  773.         new_pix = TRUE;
  774.         }
  775.     }
  776.     /* destroy any previously rotated tile or stipple */
  777.     if (!new_pix && devPriv->pRotatedPixmap)
  778.     {
  779.         mfbDestroyPixmap(devPriv->pRotatedPixmap);
  780.         devPriv->pRotatedPixmap = (PixmapPtr)NULL;
  781.     }
  782.     }
  783.  
  784.     /*
  785.      * duck out here when the GC is unchanged
  786.      */
  787.  
  788.     if (!changes)
  789.     return;
  790.  
  791.     if (new_rrop || new_fill)
  792.     {
  793.     rrop = mfbReduceRop(pGC->alu, pGC->fgPixel);
  794.     devPriv->rop = rrop;
  795.     new_fill = TRUE;
  796.     /* FillArea raster op is GC's for tile filling,
  797.        and the reduced rop for solid and stipple
  798.     */
  799.     if (pGC->fillStyle == FillTiled)
  800.         devPriv->ropFillArea = pGC->alu;
  801.     else
  802.         devPriv->ropFillArea = rrop;
  803.  
  804.     /* opaque stipples:
  805.        fg    bg    ropOpStip    fill style
  806.        1    0    alu        tile
  807.        0    1    inverseAlu    tile
  808.        1    1    rrop(fg, alu)    solid
  809.        0    0    rrop(fg, alu)    solid
  810.     Note that rrop(fg, alu) == mfbPrivGC.rop, so we don't really need to
  811.     compute it.
  812.     */
  813.         if (pGC->fillStyle == FillOpaqueStippled)
  814.         {
  815.         if (pGC->fgPixel != pGC->bgPixel)
  816.         {
  817.             if (pGC->fgPixel)
  818.             devPriv->ropOpStip = pGC->alu;
  819.             else
  820.             devPriv->ropOpStip = InverseAlu[pGC->alu];
  821.         }
  822.         else
  823.             devPriv->ropOpStip = rrop;
  824.         devPriv->ropFillArea = devPriv->ropOpStip;
  825.         }
  826.     }
  827.     else
  828.     rrop = devPriv->rop;
  829.  
  830.     if (new_line || new_fill || new_text)
  831.     {
  832.     GCOps    *newops;
  833.  
  834.     if (newops = matchCommon (pGC))
  835.      {
  836.         if (pGC->ops->devPrivate.val)
  837.         mfbDestroyOps (pGC->ops);
  838.         pGC->ops = newops;
  839.         new_line = new_fill = new_text = 0;
  840.     }
  841.      else
  842.      {
  843.         if (!pGC->ops->devPrivate.val)
  844.          {
  845.         pGC->ops = mfbCreateOps (pGC->ops);
  846.         pGC->ops->devPrivate.val = 1;
  847.         }
  848.     }
  849.     }
  850.  
  851.     if (new_line || new_fill)
  852.     {
  853.     if (pGC->lineWidth == 0)
  854.     {
  855.         if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid)
  856.         && ((rrop == RROP_WHITE) || (rrop == RROP_BLACK)))
  857.         pGC->ops->PolyArc = mfbZeroPolyArcSS;
  858.         else
  859.         pGC->ops->PolyArc = miZeroPolyArc;
  860.     }
  861.     else
  862.         pGC->ops->PolyArc = miPolyArc;
  863.     if (pGC->lineStyle == LineSolid)
  864.     {
  865.         if(pGC->lineWidth == 0)
  866.         {
  867.             if (pGC->fillStyle == FillSolid)
  868.         {
  869.             pGC->ops->PolySegment = mfbSegmentSS;
  870.             pGC->ops->Polylines = mfbLineSS;
  871.             }
  872.          else
  873.         {
  874.             pGC->ops->PolySegment = miPolySegment;
  875.             pGC->ops->Polylines = miZeroLine;
  876.         }
  877.         }
  878.         else
  879.         {
  880.         pGC->ops->PolySegment = miPolySegment;
  881.         pGC->ops->Polylines = miWideLine;
  882.         }
  883.     }
  884.     else
  885.     {
  886.         if(pGC->lineWidth == 0 && pGC->fillStyle == FillSolid)
  887.         {
  888.             pGC->ops->Polylines = mfbLineSD;
  889.         pGC->ops->PolySegment = mfbSegmentSD;
  890.         }
  891.         else
  892.         {
  893.             pGC->ops->Polylines = miWideDash;
  894.         pGC->ops->PolySegment = miPolySegment;
  895.         }
  896.     }
  897.     }
  898.  
  899.     if (new_text || new_fill)
  900.     {
  901.     if ((pGC->font) &&
  902.         (pGC->font->pFI->maxbounds.metrics.rightSideBearing -
  903.          pGC->font->pFI->minbounds.metrics.leftSideBearing) > 32)
  904.     {
  905.         pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
  906.         pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
  907.     }
  908.     else
  909.     {
  910.         /* special case ImageGlyphBlt for terminal emulator fonts */
  911.         if ((pGC->font) &&
  912.         (pGC->font->pFI->terminalFont) &&
  913.         (pGC->fgPixel != pGC->bgPixel))
  914.         {
  915.         /* pcc bug makes this not compile...
  916.         pGC->ops->ImageGlyphBlt = (pGC->fgPixel) ? mfbTEGlyphBltWhite :
  917.                               mfbTEGlyphBltBlack;
  918.         */
  919.         if (pGC->fgPixel)
  920.             pGC->ops->ImageGlyphBlt = mfbTEGlyphBltWhite;
  921.         else
  922.             pGC->ops->ImageGlyphBlt = mfbTEGlyphBltBlack;
  923.         }
  924.         else
  925.         {
  926.             if (pGC->fgPixel == 0)
  927.             pGC->ops->ImageGlyphBlt = mfbImageGlyphBltBlack;
  928.             else
  929.             pGC->ops->ImageGlyphBlt = mfbImageGlyphBltWhite;
  930.         }
  931.  
  932.         /* now do PolyGlyphBlt */
  933.         if (pGC->fillStyle == FillSolid ||
  934.         (pGC->fillStyle == FillOpaqueStippled &&
  935.          pGC->fgPixel == pGC->bgPixel
  936.         )
  937.            )
  938.         {
  939.         if (rrop == RROP_WHITE)
  940.             pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltWhite;
  941.         else if (rrop == RROP_BLACK)
  942.             pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltBlack;
  943.         else if (rrop == RROP_INVERT)
  944.             pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltInvert;
  945.         else
  946.             pGC->ops->PolyGlyphBlt = NoopDDA;
  947.         }
  948.         else
  949.         {
  950.         pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
  951.         }
  952.     }
  953.     }
  954.  
  955.     if (new_fill)
  956.     {
  957.     /* install a suitable fillspans and pushpixels */
  958.     pGC->ops->PushPixels = mfbPushPixels;
  959.     if ((pGC->fillStyle == FillSolid) ||
  960.         ((pGC->fillStyle == FillOpaqueStippled) &&
  961.          (pGC->fgPixel == pGC->bgPixel)))
  962.     {
  963.         pGC->ops->PushPixels = mfbSolidPP;
  964.         switch(devPriv->rop)
  965.         {
  966.           case RROP_WHITE:
  967.         pGC->ops->FillSpans = mfbWhiteSolidFS;
  968.         break;
  969.           case RROP_BLACK:
  970.         pGC->ops->FillSpans = mfbBlackSolidFS;
  971.         break;
  972.           case RROP_INVERT:
  973.         pGC->ops->FillSpans = mfbInvertSolidFS;
  974.         break;
  975.           case RROP_NOP:
  976.         pGC->ops->FillSpans = NoopDDA;
  977.         break;
  978.         }
  979.     }
  980.     /* beyond this point, opaqueStippled ==> fg != bg */
  981.     else if (((pGC->fillStyle == FillTiled) ||
  982.           (pGC->fillStyle == FillOpaqueStippled)) &&
  983.          !devPriv->pRotatedPixmap)
  984.     {
  985.         pGC->ops->FillSpans = mfbUnnaturalTileFS;
  986.     }
  987.     else if ((pGC->fillStyle == FillStippled) && !devPriv->pRotatedPixmap)
  988.     {
  989.         pGC->ops->FillSpans = mfbUnnaturalStippleFS;
  990.     }
  991.     else if (pGC->fillStyle == FillStippled)
  992.     {
  993.         switch(devPriv->rop)
  994.         {
  995.           case RROP_WHITE:
  996.         pGC->ops->FillSpans = mfbWhiteStippleFS;
  997.         break;
  998.           case RROP_BLACK:
  999.         pGC->ops->FillSpans = mfbBlackStippleFS;
  1000.         break;
  1001.           case RROP_INVERT:
  1002.         pGC->ops->FillSpans = mfbInvertStippleFS;
  1003.         break;
  1004.           case RROP_NOP:
  1005.         pGC->ops->FillSpans = NoopDDA;
  1006.         break;
  1007.         }
  1008.     }
  1009.     else /* overload tiles to do parti-colored opaque stipples */
  1010.     {
  1011.         pGC->ops->FillSpans = mfbTileFS;
  1012.     }
  1013.     if (pGC->fillStyle == FillSolid)
  1014.         pGC->ops->PolyFillArc = mfbPolyFillArcSolid;
  1015.     else
  1016.         pGC->ops->PolyFillArc = miPolyFillArc;
  1017.     /* the rectangle code doesn't deal with opaque stipples that
  1018.        are two colors -- we can fool it for fg==bg, though
  1019.      */
  1020.     if ((((pGC->fillStyle == FillTiled) ||
  1021.           (pGC->fillStyle == FillStippled)) &&
  1022.          !devPriv->pRotatedPixmap) ||
  1023.         ((pGC->fillStyle == FillOpaqueStippled) &&
  1024.          (pGC->fgPixel != pGC->bgPixel))
  1025.        )
  1026.     {
  1027.         pGC->ops->PolyFillRect = miPolyFillRect;
  1028.     }
  1029.     else /* deal with solids and natural stipples and tiles */
  1030.     {
  1031.         pGC->ops->PolyFillRect = mfbPolyFillRect;
  1032.  
  1033.         if ((pGC->fillStyle == FillSolid) ||
  1034.         ((pGC->fillStyle == FillOpaqueStippled) &&
  1035.          (pGC->fgPixel == pGC->bgPixel)))
  1036.         {
  1037.         switch(devPriv->rop)
  1038.         {
  1039.           case RROP_WHITE:
  1040.             devPriv->FillArea = mfbSolidWhiteArea;
  1041.             break;
  1042.           case RROP_BLACK:
  1043.             devPriv->FillArea = mfbSolidBlackArea;
  1044.             break;
  1045.           case RROP_INVERT:
  1046.             devPriv->FillArea = mfbSolidInvertArea;
  1047.             break;
  1048.           case RROP_NOP:
  1049.             devPriv->FillArea = NoopDDA;
  1050.             break;
  1051.         }
  1052.         }
  1053.         else if (pGC->fillStyle == FillStippled)
  1054.         {
  1055.         switch(devPriv->rop)
  1056.         {
  1057.           case RROP_WHITE:
  1058.             devPriv->FillArea = mfbStippleWhiteArea;
  1059.             break;
  1060.           case RROP_BLACK:
  1061.             devPriv->FillArea = mfbStippleBlackArea;
  1062.             break;
  1063.           case RROP_INVERT:
  1064.             devPriv->FillArea = mfbStippleInvertArea;
  1065.             break;
  1066.           case RROP_NOP:
  1067.             devPriv->FillArea = NoopDDA;
  1068.             break;
  1069.         }
  1070.         }
  1071.         else /* deal with tiles */
  1072.         {
  1073.         devPriv->FillArea = mfbTileArea32;
  1074.         }
  1075.     } /* end of natural rectangles */
  1076.     } /* end of new_fill */
  1077. }
  1078.  
  1079. /* table to map alu(src, dst) to alu(~src, dst) */
  1080. int InverseAlu[16] = {
  1081.     GXclear,
  1082.     GXandInverted,
  1083.     GXnor,
  1084.     GXcopyInverted,
  1085.     GXand,
  1086.     GXnoop,
  1087.     GXequiv,
  1088.     GXorInverted,
  1089.     GXandReverse,
  1090.     GXxor,
  1091.     GXinvert,
  1092.     GXnand,
  1093.     GXcopy,
  1094.     GXor,
  1095.     GXorReverse,
  1096.     GXset
  1097. };
  1098.  
  1099. int
  1100. mfbReduceRop(alu, src)
  1101.     register unsigned char alu;
  1102.     register Pixel src;
  1103. {
  1104.     int rop;
  1105.     if (src == 0)    /* src is black */
  1106.     {
  1107.     switch(alu)
  1108.     {
  1109.       case GXclear:
  1110.         rop = RROP_BLACK;
  1111.         break;
  1112.       case GXand:
  1113.         rop = RROP_BLACK;
  1114.         break;
  1115.       case GXandReverse:
  1116.         rop = RROP_BLACK;
  1117.         break;
  1118.       case GXcopy:
  1119.         rop = RROP_BLACK;
  1120.         break;
  1121.       case GXandInverted:
  1122.         rop = RROP_NOP;
  1123.         break;
  1124.       case GXnoop:
  1125.         rop = RROP_NOP;
  1126.         break;
  1127.       case GXxor:
  1128.         rop = RROP_NOP;
  1129.         break;
  1130.       case GXor:
  1131.         rop = RROP_NOP;
  1132.         break;
  1133.       case GXnor:
  1134.         rop = RROP_INVERT;
  1135.         break;
  1136.       case GXequiv:
  1137.         rop = RROP_INVERT;
  1138.         break;
  1139.       case GXinvert:
  1140.         rop = RROP_INVERT;
  1141.         break;
  1142.       case GXorReverse:
  1143.         rop = RROP_INVERT;
  1144.         break;
  1145.       case GXcopyInverted:
  1146.         rop = RROP_WHITE;
  1147.         break;
  1148.       case GXorInverted:
  1149.         rop = RROP_WHITE;
  1150.         break;
  1151.       case GXnand:
  1152.         rop = RROP_WHITE;
  1153.         break;
  1154.       case GXset:
  1155.         rop = RROP_WHITE;
  1156.         break;
  1157.     }
  1158.     }
  1159.     else /* src is white */
  1160.     {
  1161.     switch(alu)
  1162.     {
  1163.       case GXclear:
  1164.         rop = RROP_BLACK;
  1165.         break;
  1166.       case GXand:
  1167.         rop = RROP_NOP;
  1168.         break;
  1169.       case GXandReverse:
  1170.         rop = RROP_INVERT;
  1171.         break;
  1172.       case GXcopy:
  1173.         rop = RROP_WHITE;
  1174.         break;
  1175.       case GXandInverted:
  1176.         rop = RROP_BLACK;
  1177.         break;
  1178.       case GXnoop:
  1179.         rop = RROP_NOP;
  1180.         break;
  1181.       case GXxor:
  1182.         rop = RROP_INVERT;
  1183.         break;
  1184.       case GXor:
  1185.         rop = RROP_WHITE;
  1186.         break;
  1187.       case GXnor:
  1188.         rop = RROP_BLACK;
  1189.         break;
  1190.       case GXequiv:
  1191.         rop = RROP_NOP;
  1192.         break;
  1193.       case GXinvert:
  1194.         rop = RROP_INVERT;
  1195.         break;
  1196.       case GXorReverse:
  1197.         rop = RROP_WHITE;
  1198.         break;
  1199.       case GXcopyInverted:
  1200.         rop = RROP_BLACK;
  1201.         break;
  1202.       case GXorInverted:
  1203.         rop = RROP_NOP;
  1204.         break;
  1205.       case GXnand:
  1206.         rop = RROP_INVERT;
  1207.         break;
  1208.       case GXset:
  1209.         rop = RROP_WHITE;
  1210.         break;
  1211.     }
  1212.     }
  1213.     return rop;
  1214. }
  1215.  
  1216. void
  1217. mfbDestroyClip(pGC)
  1218.     GCPtr    pGC;
  1219. {
  1220.     if(pGC->clientClipType == CT_NONE)
  1221.     return;
  1222.     else if (pGC->clientClipType == CT_PIXMAP)
  1223.     {
  1224.     mfbDestroyPixmap((PixmapPtr)(pGC->clientClip));
  1225.     }
  1226.     else
  1227.     {
  1228.     /* we know we'll never have a list of rectangles, since
  1229.        ChangeClip immediately turns them into a region 
  1230.     */
  1231.         (*pGC->pScreen->RegionDestroy)(pGC->clientClip);
  1232.     }
  1233.     pGC->clientClip = NULL;
  1234.     pGC->clientClipType = CT_NONE;
  1235. }
  1236.  
  1237. void
  1238. mfbChangeClip(pGC, type, pvalue, nrects)
  1239.     GCPtr        pGC;
  1240.     unsigned int    type;
  1241.     pointer        pvalue;
  1242.     int            nrects;
  1243. {
  1244.     mfbDestroyClip(pGC);
  1245.     if(type == CT_PIXMAP)
  1246.     {
  1247.     /* convert the pixmap to a region */
  1248.     pGC->clientClip = (pointer) (*pGC->pScreen->BitmapToRegion)((PixmapPtr)pvalue);
  1249.     /* you wouldn't do this if you were leaving the pixmap in
  1250.        rather than converting it.
  1251.     */
  1252.     (*pGC->pScreen->DestroyPixmap)(pvalue);
  1253.     }
  1254.     else if (type == CT_REGION)
  1255.     {
  1256.     /* stuff the region in the GC */
  1257.     pGC->clientClip = pvalue;
  1258.     }
  1259.     else if (type != CT_NONE)
  1260.     {
  1261.     pGC->clientClip = (pointer) (*pGC->pScreen->RectsToRegion)(nrects,
  1262.                             (xRectangle *)pvalue,
  1263.                             type);
  1264.     xfree(pvalue);
  1265.     }
  1266.     pGC->clientClipType = (type != CT_NONE && pGC->clientClip) ? CT_REGION :
  1267.         CT_NONE;
  1268.     pGC->stateChanges |= GCClipMask;
  1269. }
  1270.  
  1271. void
  1272. mfbCopyClip (pgcDst, pgcSrc)
  1273.     GCPtr pgcDst, pgcSrc;
  1274. {
  1275.     RegionPtr prgnNew;
  1276.  
  1277.     switch(pgcSrc->clientClipType)
  1278.     {
  1279.       case CT_PIXMAP:
  1280.     ((PixmapPtr) pgcSrc->clientClip)->refcnt++;
  1281.     /* Fall through !! */
  1282.       case CT_NONE:
  1283.     mfbChangeClip(pgcDst, pgcSrc->clientClipType, pgcSrc->clientClip, 0);
  1284.     break;
  1285.       case CT_REGION:
  1286.     prgnNew = (*pgcSrc->pScreen->RegionCreate)(NULL, 1);
  1287.     (*pgcSrc->pScreen->RegionCopy)(prgnNew,
  1288.                        (RegionPtr)(pgcSrc->clientClip));
  1289.     mfbChangeClip(pgcDst, CT_REGION, (pointer)prgnNew, 0);
  1290.     break;
  1291.     }
  1292. }
  1293.